// set defaults
var currentpage 		= 1,
	items				= [],
	alltags				= [],
	tags				= [],
	tagsJSON			= [],
	newlink				= { url: "", title: "", shown: false },
	totalpages,allitems,itemsperpage,preFilling,shownewlink;
	
function init() {
	//if (localStorage.advertised == undefined) $("marquee").marquee().show().delay(60000).fadeOut("slow");
	//localStorage.advertised = true
	
	if (localStorage.stateof == undefined) localStorage.stateof = "unread";

	$("input:radio").change(stateChange);
	if (localStorage.sortBy != undefined) $("#sortby").val(localStorage.sortBy); // set last sort option
	if (localStorage.stateof != undefined) $("input:radio[value='" + localStorage.stateof + "']").attr("checked", true); // set stateof option
	
	if (!localStorage.theme) setTheme("new");
	else setTheme();

	// check whether username/password have been entered
	if (localStorage["username"] == undefined || localStorage["username"] == "" || localStorage["password"] == undefined || localStorage["password"] == "") {
		setMessage("Username/Password has not been specified in the options.  Please go to the extension's <a href=\"options.html\">options page</a> and add this information.", "error");
	}
	else {
		$("#leftside").show();
		
		// if no pagecount defined, go with default of 16
		if (localStorage["pagecount"] == undefined || localStorage["pagecount"] == "") localStorage["pagecount"] = 16;
		// get the list, starting w/ page 1
		getList(1);
	}
}

function getList(page) {
	// start fresh
	$("#boxes").empty();
	$("#footer").hide();
	$("#status").removeClass().hide();
	
	// get the latest [unread] link counts
	// if (!stats) getStats();
	currentpage = page; // set what page to show
	itemsperpage = localStorage["pagecount"];
	tags = [];
	
	if (page==1 && !allitems) {
		populateItems(showBoxes);
	} else
		showBoxes();
}

// http://readitlaterlist.com/api/docs/#get
function populateItems(successCallback) {
	// set the parameters to pass to RIL server
	var params = {
		username: localStorage["username"],
		password: localStorage["password"],
		apikey: apikey,
		//state: "unread",
		tags: "1"
	}
	
	$.ajax({
		type: "GET",
		url: apiurl + "get",
		data: params,
		dataType: "json",
		success: function(data) {                       
			items = [];
			
			// add items to array (prepare to be sorted)
			$.each(data.list, function(i, item) { 
				//if (item.tags) item.tags.split(","); 
				items[items.length] = item; 
			});
			
			allitems = items; // backup of all items for later filtering
			
			filterItems();
			sortItems();			
			
			successCallback();
		},
		complete: function(request, status) {
			// if error encountered, say so
			if (status != "success") {
				setMessage("Error retrieving list from ReadItLaterList.com server.  Please <a href=\"options.html\">check your username/password</a> or try again later.", "error");				
			}
		}
	});
}

function sortItems() {
	var sortBy = $("#sortby").val();
	localStorage.sortBy = sortBy;
	// Credit: http://my.opera.com/GreyWyvern/blog/show.dml/1671288
	function alphanum(a, b) {
		function chunkify(t) {
			var tz = [], x = 0, y = -1, n = 0, i, j;

			while (i = (j = t.charAt(x++)).charCodeAt(0)) {
				var m = (i == 46 || (i >=48 && i <= 57));
				if (m !== n) {
					tz[++y] = "";
					n = m;
				}
				tz[y] += j;
			}
			return tz;
		}

		var aa = chunkify(a[sortBy].toLowerCase());
		var bb = chunkify(b[sortBy].toLowerCase());

		for (x = 0; aa[x] && bb[x]; x++) {
			if (aa[x] !== bb[x]) {
				var c = Number(aa[x]), d = Number(bb[x]);
				if (c == aa[x] && d == bb[x]) {
					return c - d;
				} else return (aa[x] > bb[x]) ? 1 : -1;
			}
		}
		
		return aa.length - bb.length;
	}
	
	if (sortBy == "title")
		items.sort(alphanum);
	else
		// sort times DESC
		items.sort(function(a,b) { return parseFloat(b[sortBy]) - parseFloat(a[sortBy]); });
}
	
function showBoxes() {	
	var itemsToShow = [];
	// prep for box building
	var count = 0, recend,
		recstart = (itemsperpage * (currentpage - 1)) + 1,
		stopper = recstart + Number(itemsperpage) - 1;
	
	// get list of boxes to show
	$.each(items, function(i, item) {
		count++;
		
		// limit number of items per page
		if (count >= recstart && count <= stopper) { 
			itemsToShow.push(formatNicely(item, count));			
		}
		else if (count > stopper) return false;
	});
	
	// render boxes from template
	$("#boxTemplate").tmpl(itemsToShow).appendTo("#boxes");
	
	// check "Open Links in New Tab" option, if desired, set it
	if (localStorage["opennewtab"] != undefined && localStorage["opennewtab"] == "Yes") {
		$(".box a").attr("target", "_blank");
	}
	
	buildTags();	
	showTags();
	
	if (localStorage.autoSuggest == "Yes") {
		setAutoSuggest();
	} else {
		$("input.edittag:visible").change(function() { 
			var o = this;
			editTags(o);
		});
	}
	
	showTags();
		
	if (count == 0) {
		setMessage("You don't have any unread links. Get back to work!", "info");		
	} else {
		buildFooter(itemsToShow.length);
	}
	
	//checkBoxes();
}

function formatNicely(item, itemnum) {
	var newitem = new Object();
	newitem.itemnum = itemnum;
	newitem.item = item;
	// if no title, then use the URL as title
	newitem.title = (item.title != "") ? item.title : item.url;
	// convert date to something understandable
	var d = new Date(item.time_updated*1000);
	newitem.updateDate = (d.getMonth()+1) + "/" + d.getDate() + "/" + d.getFullYear() + " " + ((d.getHours() > 12) ? d.getHours() - 12 : d.getHours()) + ":" + ((d.getMinutes() < 10) ? "0" + d.getMinutes() : d.getMinutes()) + " " + ((d.getHours() >= 12) ? "PM" : "AM");
	// extract domain name from URL
	newitem.urldomain = /(?:(\w+):\/\/)([^\/]+)/gi.exec(item.url)[0];
	newitem.domain = /(\w+):\/\/(?:([^\/]+))/gi.exec(item.url)[2];
	newitem.state = item.state;
	
	return newitem;
}

function buildTags() {
	alltags = [];
	tags = [];
	tagsJSON = { items: [] };
	
	// build list of all tags
	$.each(allitems, function(i, item) {
		if (item.tags) {
			var splittags = item.tags.split(",");
			for (var y=0; y<splittags.length; y++) {
				if (splittags[y] != "") alltags.push(splittags[y]);
			}
		}
	});
	
	alltags = alltags.unique();
	
	for (var x=0; x<alltags.length; x++) {
		tagsJSON.items.push({ value: alltags[x], name: alltags[x] });
	}
	
	// build list of current filtered items' tags
	$.each(items, function(i, item) {
		if (item.tags) tags = tags.concat(item.tags.split(","));
		if (!newlink.shown && newlink.url != "" && shownewlink && item.url == newlink.url) shownewlink = false;
	});
}

function showTags() {
	var uniqueobjects = [],
		uniquetags = [],
		newobjects = [];
	
	uniqueobjects = tags.uniqueobjects();
	
	for (var x=0; x<uniqueobjects.length; x++) {
		if (uniqueobjects[x].o != "") uniquetags.push(uniqueobjects[x].o);
	}
	
	uniquetags.sort();
	
	o:for (var x=0; x<uniquetags.length; x++) {
		for (var y=0; y<uniqueobjects.length; y++) {
			if (uniquetags[x] == uniqueobjects[y].o) {
				newobjects.push(uniqueobjects[y]);
				continue o;
			}
		}
	}
	
	var tagsEl = $("#tags");
	
	$("#tagsbox").hide();
	tagsEl.empty();
	
	//tagsJSON = { items: [] };
	
	for (var x=0; x<newobjects.length; x++) {
		tagsEl.append("<li><a size=\"" + newobjects[x].count + "\" href=\"javascript:showTag('" + newobjects[x].o + "')\">" + newobjects[x].o + "</a></li>");
		//tagsJSON.items.push({ value: newobjects[x].o, name: newobjects[x].o });
	}
	
	if (uniquetags.length > 0) {
		$("#tagsbox").show();
		
		var max = 1;
		$("a[size]").each(function(i, item) {
			if ($(item).attr("size") > max) max = $(item).attr("size");
		});
		
		$("a[size]").each(function(i, item) {
			var size = $(item).attr("size");
			var pct = Math.ceil((size / max) * 10) * 10;			
			$(item).addClass("tag-" + pct);
		});		
	}
}

var iCounter = 0;

function setAutoSuggest() {
	preFilling = true;
	$("input.edittag:not(.as-input)").each(function(i, item) {
		$(item).parent().addClass("as-control");
		iCounter++;
		var options = {
			asHtmlID: iCounter,
			startText: "", 
			selectedItemProp: "name", 
			searchObjProps: "name", 
			selectedValuesProp: "name", 
			retrieveLimit: 5,
			keyDelay: 200,
			preFill: $(item).val(),			
			selectionAdded: function(elem) {
				elem.fadeTo("slow", 1.0);
				var val = $(elem).text().substring(1);
				if (!preFilling) editTags(item);
			},
			selectionRemoved: function(elem) {
				elem.fadeTo("fast", 0, function() { elem.remove(); });
				editTags(item);				
			}
		}
		$(item).autoSuggest(tagsJSON.items, options);
	});
	preFilling = false;
}

function markRead(url, a) {
	var itemnum	= $(a).parents(".box").attr("num"),
		trash 	= $("#trash"),
		box 	= $(".box[num=" + itemnum + "]:visible");
		tOff	= trash.height()/2,
		lOff	= trash.width()/2
		
	if (localStorage.readAnimation && localStorage.readAnimation === "Enabled") {
	box.css("position", "relative").css("zIndex", "5000").animate( {
		top: trash.offset().top-box.offset().top+tOff,
		left: trash.offset().left-box.offset().left+lOff,
		width: "0px",
		height: "0px"
		}, 1500, function() {
			box.hide();
			trash.removeClass().addClass("full");
		});
	} else {
		box.slideUp();
	}
	
	setRead(url, itemnum);
}

// http://readitlaterlist.com/api/docs/#send
function setRead(url, itemnum) {
	// set the parameters to pass to RIL server
	url = url.replace("\"", "\\\""); // bug fix: for URLs that contain a double quote
	
	var params = {
		username: localStorage["username"],
		password: localStorage["password"],
		apikey: apikey,
		read: '{"0":{"url":"'+url+'"}}'
	}
	
	$.ajax({
		url: apiurl + "send",
		data: params,
		success: function(data) {
			var item = items[itemnum - 1];
			var title = (item.title != "") ? item.title : item.url;
			// hide/fade the read link
			//$("#box" + itemnum).fadeOut(1000);
			setMessage("\"" + title + "\" was successfully marked read.", "info").delay(5000).fadeOut("slow");
			
			items.splice(itemnum - 1, 1);
			
			$("input.edittag").each(function(i, item) {
				var c = $(this);
				if (parseInt(c.attr("num")) > parseInt(itemnum)) {
					c.attr("num", c.attr("num") - 1);
					c.parents(".box").attr("num", c.attr("num"));
				}
			});
			
			if (itemnum > items.length && currentpage > 1) // last item on last page, change to previous page
				getList(currentpage - 1);
				
			else if (currentpage<totalpages) { // if not on last page, add another item
				var nextItem = (currentpage*itemsperpage);
				if ((nextItem - 1) <= items.length) {
					$("#boxTemplate").tmpl(formatNicely(items[nextItem-1], nextItem)).hide().appendTo("#boxes").hide(0, function() { 
						if (localStorage.autoSuggest == "Yes") setAutoSuggest();
					}).delay(1200).slideDown("slow");
					
					buildFooter();
				}
			}
			else {
				buildFooter(items.length);
			}
		},
		complete: function(request, status) {
			// if error encountered, say so
			if (status != "success") {
				setMessage("Error marking link read.", "error");				
			}
		}               
	});
}

function sendTags(url, tags, successCallback) {
	// set the parameters to pass to RIL server
	var params = {
		username: localStorage.username,
		password: localStorage.password,
		apikey: apikey,
		update_tags: '{"0":{"url":"'+url+'","tags":"'+tags+'"}}'
	}
	
	$.ajax({
		url: apiurl + "send",
		data: params,
		success: successCallback,
		complete: function(request, status) {
			// if error encountered, say so
			if (status != "success") {
				setMessage("Error tagging link.", "error");
			}
		}               
	});
}

// http://readitlaterlist.com/api/docs/#auth
function auth(completeCallback) {
	// set the parameters to pass to RIL server
	var params = {
		username: localStorage["username"],
		password: localStorage["password"],
		apikey: apikey
	}
	
	$.ajax({
		url: apiurl + "auth",
		data: params,
		complete: completeCallback
	});
}

// http://readitlaterlist.com/api/docs/#add
function add(url, title, successCallback, completeCallback) {
	// set the parameters to pass to RIL server
	var params = {
		username: localStorage["username"],
		password: localStorage["password"],
		apikey: apikey,
		url: url,
		title: title
	}
	
	$.ajax({
		url: apiurl + "add",
		data: params,
		complete: completeCallback,
		success: successCallback
	});
}

function getStats() {
	// set the parameters to pass to RIL server
	var params = {
		username: localStorage["username"],
		password: localStorage["password"],
		apikey: apikey
	}

	$.ajax({
		url: apiurl + "stats",
		data: params,
		contentType: "text/json",               
		success: function(data) {
			// set global variables with the stats returned
			stats = data;
		}
	});
}

function buildFooter(itemsOnPage) {
	// calculate paging parameters
	var recstart, recend;
	recstart = (itemsperpage * (currentpage - 1)) + 1;
	recend = Number((itemsOnPage) ? itemsOnPage : itemsperpage) + recstart - 1;
	
	totalpages = Math.ceil(items.length/localStorage["pagecount"]);
		
	$("#reccount").html(recstart + "-" + recend);
	$("#rectotal").html(items.length);
	$("#pagecount").html(totalpages);
	
	// setup paging dropdown
	$("#pagenum").empty()
	for (var x=1; x<=totalpages; x++) $("#pagenum").append("<option " + ((x == currentpage) ? "selected" : "") + ">" + x + "</option>");
			
	// enable/disable next/previous
	if (currentpage == 1) $("#previouspage").addClass("disable"); else $("#previouspage").removeClass("disable");
	if (currentpage == totalpages) $("#nextpage").addClass("disable"); else $("#nextpage").removeClass("disable");
	
	$("#footer").show();
}

function editTags(boxinput, tags) {
	var itemnum = boxinput.attributes["num"].value;
	
	if (!tags && localStorage.autoSuggest == "Yes") {
		tags = $("#as-values-" + boxinput.id).val();
	} else {
		tags = boxinput.value;
	}
	
	items[itemnum-1].tags = tags;
	sendTags(items[itemnum-1].url, tags, function(data) {
		//getList(currentpage);
		buildTags();
		showTags();		
	});
}

function showTag(tag) {
	$("#searchbox").focus().val("tag:" + tag);
	filtering();
}

// paging functions

function nextPage() {
	if (currentpage < totalpages) currentpage++;
	getList(currentpage);
}

function previousPage() {
	if (currentpage > 1) currentpage--;
	getList(currentpage);
}


// left side functions

function filtering() {
	items = allitems; // reload from backup
	
	// filter based on text search (this includes tag filtering)
	var filterText = $("#searchbox").val();
	if (filterText != "Search" && filterText != "") filter(filterText);
	// filter based on state selection
	filterItems();
	
	// set the stage
	currentpage = 1;
	
	// start fresh
	$("#boxes").empty();
	$("#footer").hide();
	$("#status").removeClass().hide();
	
	if (items.length == 0)
		setMessage("No links contain a title, url, or tag with the text specified, \"" + text + "\". Please try another search.", "error");		
	else 
		showBoxes(); // show filtered set
}

function filterItems() {
	var filteredItems = [];
	
	if (localStorage.stateof != "all") { // filter by state of
		$.each(items, function(i, item) {		
			if (item && item.state && ((item.state == "1" && localStorage.stateof == "read") || (item.state == "0" && localStorage.stateof == "unread"))) {
				filteredItems.push(item); // add item
			}
		});
		
		items = filteredItems;
	}
}

function filter(text) {		
	// filter items
	var filteredItems = [];
	text = text.toLowerCase();
	var searchText = text;
	
	$.each(items, function(i, item) {
		if (text.indexOf("tag:") == 0) {
			// search only tags
			searchText = text.substring(4);			
			if (item.tags && item.tags.toLowerCase().indexOf(searchText) != -1)
				filteredItems.push(item);
		} else if (text.indexOf("url:") == 0) {
			// search only url
			searchText = text.substring(4);			
			if (item.url.toLowerCase().indexOf(searchText) != -1)
				filteredItems.push(item);
		} else if (text.indexOf("title:") == 0) {
			// search only title
			searchText = text.substring(6);
			if (item.title.toLowerCase().indexOf(searchText) != -1)
				filteredItems.push(item);
		} else {
		// check title, url, tags for text
			if (item.title.toLowerCase().indexOf(searchText) != -1 || item.url.toLowerCase().indexOf(searchText) != -1 || (item.tags && item.tags.toLowerCase().indexOf(searchText) != -1))
			filteredItems.push(item);
		}		
	});
	
	items = filteredItems;
}

function sort() {
	// start fresh
	$("#boxes").empty();
	// apply sort
	sortItems();
	showBoxes();
}

function stateChange(a) {
	localStorage.stateof = $("input:radio:checked").val();
	filtering();
}

function refresh() {
	allitems = null;
	getList(1);
}

function setMessage(message, className) {
	var o = $("#status")
		.removeClass()
		.html(message)
		.addClass(className);
		
	var cl = $("<div id='status-close'></div>").click(function() { o.hide(); }).prependTo(o);
		
	if (localStorage.theme == "new")
		return o.slideDown();
	else
		return o.show();
}

var dragdrop = { url: null, id: null, itemnum: null }

function boxdrag(target, e) {
	//$("a.link").attr("href")
	var url = $("a.link", target).attr("href");
	var itemnum = $("input.edittag", target).attr("num");
	
	dragdrop.id = target.id;
	dragdrop.url = url;
	dragdrop.itemnum = itemnum;
}

function boxdrop(target, e) {
	e.preventDefault();
	
	$("#" + dragdrop.id).hide();	
	setRead(dragdrop.url, dragdrop.itemnum);
	$("#trash").removeClass().addClass("full");
}

function setTheme(themeName) {
	if (themeName) localStorage.theme = themeName;
	$("link.theme").attr("href", "../css/themes/" + localStorage.theme + ".css");
}

function checkBoxes() {
	$("div.box:visible input.edittag").each(function(i, item) {
		var num = $(item).attr("num");
		var href = $(item).parents(".box").find("a.link").attr("href");
		
		$(item).prepend(num + ",");
		
		if (items[num-1].url != href) console.debug("num " + num + " does not match. " + href + " <> " + items[num-1].url);
	});
}

Array.prototype.uniqueobjects = function () {
	var r = new Array();
	o:for(var i = 0, n = this.length; i < n; i++)
	{
		for(var x = 0, y = r.length; x < y; x++)
		{
			if(r[x].o==this[i])
			{
				r[x].count++;
				continue o;
			}
		}
		r[r.length] = { o: this[i], count: 1 };
	}
	return r;
}

Array.prototype.unique = function() {
	var newArray=new Array();
	label:for(var i=0; i<this.length;i++ )
	{  
		for(var j=0; j<newArray.length;j++ )
		{
			if(newArray[j]==this[i]) 
				continue label;
		}
		newArray[newArray.length] = this[i];
	}
	return newArray;
}